package com.itdct.onflow.generator.template.web

import com.itdct.onflow.core.entity.BaseUserEntity
import com.itdct.onflow.generator.config.GeneratorConfig
import com.itdct.onflow.generator.model.ClassModel
import com.itdct.onflow.generator.model.CompareResultModel
import com.itdct.onflow.generator.model.FieldModel

/**
 * @author Zhouwx
 * @date 2025/8/26 18:29:50
 * @version 1.0
 * @description
 */
class VueWriteTemplate(classModel: ClassModel, generatorConfig: GeneratorConfig) : BaseVueTemplate(classModel, generatorConfig) {
    init {
        filterFieldList.add("id")
        filterFieldList.add("del")
        filterFieldList.add("version")
        filterFieldList.add("deleteUser")
        filterFieldList.add("deleteTime")
        filterFieldList.add("createUser")
        filterFieldList.add("updateUser")
        filterFieldList.add("createTime")
        filterFieldList.add("updateTime")
    }

    override fun restPath(): String {
        return "components/${classModel.className}Write.vue"
    }

    override fun render(): String {
        return """
<script setup lang="tsx">
import { Form, FormSchema } from '@/components/Form'
import { PropType, reactive, ref } from 'vue'
import { useValidator } from '@/hooks/web/useValidator'
import { ${classModel.className}DetailVo } from '@/api/${apiPath()}/types'
import { isBlank } from '@/utils/StringUtils'
import { useBaseWriteView } from '@/base/views/BaseWriteView'
import { sysDictChooseListApi } from '@/api/system/dict/SysDict'
import { KeyLabelValueVo } from '@/base/api/KeyLabelValueVo'
${rangeStart("selectFunctionImport")}
${selectFunctionImport()}
${rangeEnd("selectFunctionImport")}

const { required } = useValidator()

const props = defineProps({
  currentRow: {
    type: Object as PropType<Nullable<${classModel.className}DetailVo>>,
    default: () => null
  },
  editType: {
    type: String,
    default: 'add'
  },
  editId: {
    type: Number,
    default: -1
  }
})
const isAdd = ref(props.editType === 'add')

const { formRegister, submit, doWatch } = useBaseWriteView(props)
doWatch()

const formRef = ref<typeof Form>()
${rangeStart("dictFunctions")}
${renderDictFunctions()}
${rangeEnd("dictFunctions")}

${rangeStart("selectFunctions")}
${renderSelectFunctions()}
${rangeEnd("selectFunctions")}

const schema = reactive<FormSchema[]>([
  ${rangeStart("inputSchema")}
${renderInputSchema()}
  ${rangeEnd("inputSchema")}
  {
    field: 'createTime',
    label: '创建时间',
    component: 'Input',
    remove: isAdd.value,
    componentProps: {
      placeholder: '暂无创建时间',
      disabled: true
    }
  },
  {
    field: 'updateTime',
    label: '更新时间',
    component: 'Input',
    remove: isAdd.value,
    componentProps: {
      placeholder: '暂无更新时间',
      disabled: true
    }
  }${createUpdateUserInfo()}
])

const rules = reactive({
  ${rangeStart("rules")}
${renderFieldRules()}
  ${rangeEnd("rules")}
})

defineExpose({
  submit
})
</script>

<template>
  <Form :rules="rules" @register="formRegister" :schema="schema" ref="formRef" />
</template>

        """.trimIndent()
    }

    private fun createUpdateUserInfo(): String {
        val clazz = classModel.clazz ?: return ""
        if (BaseUserEntity::class.java.isAssignableFrom(clazz)) {
            return ",\n" + """
|  {
|    field: 'createUserName',
|    label: '创建人',
|    component: 'Input',
|    remove: isAdd.value,
|    componentProps: {
|      placeholder: '暂无创建人',
|      disabled: true
|    }
|  },
|  {
|    field: 'updateUserName',
|    label: '更新人',
|    component: 'Input',
|    remove: isAdd.value,
|    componentProps: {
|      placeholder: '暂无更新人',
|      disabled: true
|    }
|  }
            """.trimMargin()
        } else {
            return ""
        }
    }

    private fun renderFieldRules(): String {
        return fieldsGen("", classModel.fieldList, { i, fieldModel ->
            """
${fieldRulesContent(fieldModel)}
            """.trimMargin()
        }, ",\n")
    }

    private fun fieldRulesContent(fieldModel: FieldModel): String {
        if (fieldModel.nullable && fieldModel.kClass != String::class) {
            return ""
        }
        val ruleNameList = ArrayList<String>()
        if (!fieldModel.nullable) {
            ruleNameList.add("notNull")
        }

        if (fieldModel.kClass == String::class) {
            ruleNameList.add("length")
        }

        if (ruleNameList.size == 1 && ruleNameList[0] == "notNull") {
            return """
|  ${fieldModel.name}: [required()]
        """.trimMargin()
        } else {
            return """
  ${fieldModel.name}: [
${renderRules(fieldModel, ruleNameList)}
  ]
            """.trimMargin()
        }


    }

    private fun renderRules(fieldModel: FieldModel, ruleNameList: ArrayList<String>): String {
        return ruleNameList.map {
            singleRuleContent(fieldModel, it)
        }.joinToString(",\n")
    }

    private fun singleRuleContent(fieldModel: FieldModel, it: String): String {
        when (it) {
            "notNull" -> {
                return """
|    required()
                """.trimMargin()
            }

            "length" -> {
                return """
|    {
|      validator: (_, value, callback) => {
|        if (isBlank(value)) {
|          callback()
|          return
|        }
|        if (value.length > ${fieldModel.length}) {
|          callback(new Error('${fieldModel.comment}不能超过${fieldModel.length}个字符'))
|        } else {
|          callback()
|        }
|      }
|    }
                """.trimMargin()
            }

            else -> {
                return ""
            }
        }
    }

    private fun renderInputSchema(): String {
        return fieldsGen("", classModel.fieldList, { i, fieldModel ->
            inputSchemaContent(fieldModel)
        }, ",\n") + ","
    }

    private fun inputSchemaContent(fieldModel: FieldModel) = """
    |  {
    |    field: '${fieldModel.name}',
    |    label: '${targetClassIdLabel(fieldModel)}',${setDefaultValue(fieldModel)}
    |    component: '${getVueComponentType(fieldModel)}',
    |    componentProps: {
    |      placeholder: '${placeholder(fieldModel)}'${extraOptions(fieldModel)}
    |    }
    |  }
                """.trimMargin()

    private fun setDefaultValue(fieldModel: FieldModel): String {
        var defaultValue = fieldModel.defaultValue
        if (defaultValue.isBlank()) {
            if (fieldModel.vueComponentType == "Switch") {
                return "\n" + """
|    value: false,
            """.trimMargin()
            }
            return ""
        } else {
            if (fieldModel.vueComponentType == "Switch") {
                defaultValue = if (defaultValue == "1") "true" else "false"
                return "\n" + """
|    value: ${defaultValue},
            """.trimMargin()
            }
            return "\n" + """
|    value: '${defaultValue}',
            """.trimMargin()
        }
    }

    private fun extraOptions(fieldModel: FieldModel): String {
        if (fieldModel.name == "createTime" || fieldModel.name == "updateTime") {
            return ",\n" + """
|      disabled: true
            """.trimMargin()
        }

        var extra = ""
        val vueComponentType = fieldModel.vueComponentType
        if (vueComponentType == "Select") {
            var optionName = ""
            if (fieldModel.targetClass != null) {
                optionName = "${firstLetterLower(fieldModel.targetClassName)}${firstLetterUpper(fieldModel.targetFieldName)}List"
            }
            if (fieldModel.dictCode.isNotBlank()) {
                optionName = "${fieldModel.name}Options"
            }
            extra = "," + """
|
|      clearable: true,
|      filterable: true,
|      options: ${optionName}
            """.trimMargin()
        } else if (vueComponentType == "DatePicker") {
            extra = "," + """
|
|      clearable: true,
|      type: 'datetime',
|      valueFormat: 'YYYY-MM-DD HH:mm:ss'
            """.trimMargin()
        } else if (vueComponentType == "Input" || vueComponentType == "InputNumber") {
            extra = "," + """
|
|      clearable: true
            """.trimMargin()
        }
        return extra
    }

    private fun getVueComponentType(fieldModel: FieldModel): String {
        // INFO: Zhouwx: 2025/8/27 创建时间和更新时间不让改的，因此还是输入框
        if (fieldModel.name == "createTime" || fieldModel.name == "updateTime") {
            return "Input"
        }

        return fieldModel.vueComponentType
    }

    private fun placeholder(fieldModel: FieldModel): String {
        if (fieldModel.vueComponentType == "Input") {
            return "请输入${fieldModel.comment}"
        } else {
            return "请选择${fieldModel.comment}"
        }
    }

//    private fun fieldLabel(fieldModel: FieldModel): String {
//        val comment = fieldModel.comment
//        if (comment.endsWith("Id")) {
//            return comment.substring(0, comment.length - 2)
//        } else {
//            return comment
//        }
//    }

    override fun onModify(compareResultModel: CompareResultModel, content: String): String {
        var content = content
        // INFO: Zhouwx: 2025/9/3 处理导入import行
        val addForSelectFields = compareResultModel.addForSelect
        var addIndex = content.indexOf(rangeEnd("selectFunctionImport"))
        content = insertFieldListContent(content, addForSelectFields, addIndex, { index, fieldModel -> selectFunctionImportContent(fieldModel) })

        val delForSelect = compareResultModel.delForSelect
        content = deleteRangeFunctionCode(content, "selectFunctionImport", delForSelect, { fieldModel -> selectFunctionImportContent(fieldModel) })

        // INFO: Zhouwx: 2025/9/3 处理字典相关内容
        val addDicts = compareResultModel.addDict
        addIndex = content.indexOf(rangeEnd("dictFunctions"))
        content = insertFieldListContent(content, addDicts, addIndex, { index, fieldModel -> selectDictContent(fieldModel) })

        val delDicts = compareResultModel.delDict
        content = deleteRangeFunctionCode(content, "dictFunctions", delDicts, { fieldModel -> selectDictContent(fieldModel) })

        val modifyDicts = compareResultModel.modifyDict
        content = modifyReplace(content, "dictFunctions", modifyDicts, { fieldModel -> selectDictContent(fieldModel) })

        // INFO: Zhouwx: 2025/9/3 处理下拉选相关内容
        addIndex = content.indexOf(rangeEnd("selectFunctions"))
        content = insertFieldListContent(content, addForSelectFields, addIndex, { index, fieldModel -> selectFunctionContent(fieldModel) })

        content = deleteRangeFunctionCode(content, "selectFunctions", delForSelect, { fieldModel -> selectFunctionContent(fieldModel) })

        // INFO: Zhouwx: 2025/9/3 处理输入框
        addIndex = content.indexOf(rangeEnd("inputSchema"))
        content = insertFieldListContent(content, addForSelectFields, addIndex, { index, fieldModel -> inputSchemaContent(fieldModel) })

        content = deleteRangeFunctionCode(content, "inputSchema", delForSelect, { fieldModel -> inputSchemaContent(fieldModel) })

        val modifyPairs = compareResultModel.modifyPairs
        content = modifyReplace(content, "inputSchema", modifyPairs, { fieldModel -> inputSchemaContent(fieldModel) })

        // INFO: Zhouwx: 2025/9/3 处理数据框的判断规则
        addIndex = content.indexOf(rangeEnd("rules"))
        content = insertFieldListContent(content, addForSelectFields, addIndex, { index, fieldModel -> fieldRulesContent(fieldModel) })

        content = deleteRangeFunctionCode(content, "rules", delForSelect, { fieldModel -> fieldRulesContent(fieldModel) })

        content = modifyReplace(content, "rules", modifyPairs, { fieldModel -> fieldRulesContent(fieldModel) })


        return content
    }

    override fun subModuleName(): String {
        return "views"
    }
}